package com.naiterui.ehp.bs.b2c.product.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bs.b2c.common.bo.inventory.StockBO;
import com.naiterui.ehp.bs.b2c.inventory.service.IStockService;
import com.naiterui.ehp.bs.b2c.product.entity.Medicine;
import com.naiterui.ehp.bs.b2c.product.entity.Product;
import com.naiterui.ehp.bs.b2c.product.entity.Sku;
import com.naiterui.ehp.bs.b2c.product.exception.ProductBusinessException;
import com.naiterui.ehp.bs.b2c.product.exception.ProductExceptionCodes;
import com.naiterui.ehp.bs.b2c.product.repository.IMedicineRepository;
import com.naiterui.ehp.bs.b2c.product.repository.IProductRepository;
import com.naiterui.ehp.bs.b2c.product.repository.ISkuRepository;
import com.naiterui.ehp.bs.b2c.product.service.IProductService;
import com.naiterui.ehp.bs.b2c.product.service.ISkuImageService;
import com.naiterui.ehp.bs.b2c.product.vo.ProductAttrVO;
import com.naiterui.ehp.bs.b2c.product.vo.ProductDetailVO;
import com.naiterui.ehp.bs.b2c.product.vo.ProductImgVO;
import com.naiterui.ehp.bs.b2c.product.vo.ProductInfoVO;
import com.naiterui.ehp.bs.b2c.thirdparty.service.IPrescriptionPlatformService;

import cn.hutool.core.collection.CollectionUtil;

@Service
public class ProductServiceImpl implements IProductService {

    private static final String IMG_URL_PRE_SKU = ConfigUtil.getString("img.url.pre.sku");

    @Autowired
    private ISkuRepository skuRepository;
    @Autowired
    private IProductRepository productRepository;
    @Autowired
    private IMedicineRepository medicineRepository;
    @Autowired
    private IStockService stockService;
    @Autowired
    private ISkuImageService skuImageService;
    @Autowired
    private IPrescriptionPlatformService platformService;

    /**
     * 分类/关键字搜索商品
     */
    @Override
    public PageVO<ProductInfoVO> getProductList(PageParamVO pageParamVO, Integer categoryId, String keyword) {
        List<ProductInfoVO> result = new ArrayList<>();
        Page<Sku> skuPage = null;
        Pageable pageable = pageParamVO.getPageable(Sort.by(Sort.Order.desc("createdAt")));
        if (null != categoryId) {
            // 分类搜索
            skuPage = this.skuRepository.findSkuByCategoryIdAndStatusPageable(Long.parseLong(categoryId.toString()), Sku.STATUS_UP, pageable);
        } else if (StringUtils.isNotEmpty(keyword)) {
            // 关键字搜索
            skuPage = this.skuRepository.findByNameLikeAndStatusAndDefaultSku("%" + keyword + "%", Sku.STATUS_UP,
                Sku.DEFAULT_SKU_YES, pageable);
        } else {
            //搜索全部
            skuPage = this.skuRepository.findByStatusAndDefaultSku(Sku.STATUS_UP, Sku.DEFAULT_SKU_YES, pageable);
        }
        if (skuPage.getTotalElements() == 0) {
            return PageVO.newBuilder()
                    .pageNo(pageParamVO.getPage())
                    .pageSize(pageParamVO.getNum())
                    .totalCount((int) skuPage.getTotalElements())
                    .result(Lists.newArrayList()).build();
        }
        List<Sku> skuList = skuPage.getContent();
        Set<String> numbers = new HashSet<>();
        // 涉及pid
        Set<Long> pIds = new HashSet<>();
        Optional.ofNullable(skuList).ifPresent(list -> list.forEach(sku -> {
            pIds.add(sku.getProductId());
            numbers.add(sku.getNumber());
        }));
        Map<Long, Medicine> medicineMap = this.getMapToMedicine(pIds);

        Optional.ofNullable(skuList).ifPresent(list -> list.forEach(sku -> {
            Medicine medicine = medicineMap.get(sku.getProductId());
            ProductInfoVO productInfoVO = ProductInfoVO.builder()
                    .productId(sku.getProductId())
                    .skuId(sku.getId())
                    .number(sku.getNumber())
                    .name(sku.getName().contains("null") ? sku.getName().replaceAll("null", "").trim() : sku.getName().trim())
                    .icon(this.skuImageService.getSkuIcon(sku.getId()))
                    .rx(medicine.getNmpaType())
                    .salePrice(sku.getSalePrice())
                    .company(medicine.getProductionEnterprise())
                    .status(sku.getStatus())
                    .spec(medicine.getSpecification())
                    .usage(medicine.getUsageDosage())
                    .inventoryWarningValue(sku.getInventoryWarningValue())
                    .build();
            result.add(productInfoVO);
        }));
        return PageVO.newBuilder()
                .pageNo(pageParamVO.getPage())
                .pageSize(pageParamVO.getNum())
                .totalCount((int) skuPage.getTotalElements())
                .result(result).build();
    }

    /**
     * 查询sku列表对应medicine映射
     *
     * @param pIds
     * @return
     */
    @Override
    public Map<Long, Medicine> getMapToMedicine(Set<Long> pIds) {
        if (CollectionUtil.isEmpty(pIds)) {
            return Maps.newHashMap();
        }
        List<Medicine> medicineList = this.medicineRepository.findAllByProductIdIn(pIds);

        return Optional.ofNullable(medicineList)
                .map(medicines -> medicines.stream().collect(Collectors.toMap(Medicine::getProductId, e -> e)))
                .orElseGet(Maps::newHashMap);
    }

    /**
     * 商品详情
     *
     * @param skuId
     * @return
     */
    @Override
    public ProductDetailVO getProductDetail(Long skuId) throws ProductBusinessException {
        Sku sku = this.skuRepository.get(skuId);
        if (null == sku) {
            throw new ProductBusinessException(ProductExceptionCodes.PRODUCT_NOT_FOUND);
        }
        Product p = this.productRepository.get(sku.getProductId());
        if (null == p) {
            throw new ProductBusinessException(ProductExceptionCodes.PRODUCT_NOT_FOUND);
        }
        ProductDetailVO result = new ProductDetailVO(sku.getProductId(), sku.getId(), sku.getName(), p.getCommonName(), p.getNmpaType(), null,
                "", sku.getSalePrice(), 0L, null, sku.getStatus(), null, null);

        // 商品图片
        List<ProductImgVO> imgs = new ArrayList<>();
        // 商品大小图对应
        Map<String, String> imgMap = this.skuImageService.imgMap(sku.getId());
        // 商品小图集合
        Set<String> littles = imgMap.keySet();
        Optional.ofNullable(littles).ifPresent(lts -> lts.forEach(little -> {
            imgs.add(new ProductImgVO(IMG_URL_PRE_SKU + little, IMG_URL_PRE_SKU + imgMap.get(little)));
        }));
        result.setImgs(imgs);
        // 中间部分单独展示规格属性
        result.setUpper(this.getUpperAttr(p));
        // 规格属性
        result.setLower(this.getLowerAttr(p));
        // 库存数量
        StockBO bo = this.stockService.getStock(sku.getId());
        result.setQuantity(null != bo ? bo.getRemainQuantity() : 0L);
        return result;
    }


    private List<ProductAttrVO> getUpperAttr(Product product) {
        List<ProductAttrVO> attrs = new ArrayList<>();
        switch (product.getType()) {
            case Product.TYPE_MEDICINE:
                Medicine medicine = this.medicineRepository.findByProductId(product.getId());
                if (medicine != null) {
                    attrs.add(new ProductAttrVO("用法用量", medicine.getUsageDosage()));
                    attrs.add(new ProductAttrVO("功能主治", medicine.getIndications()));
                }
                break;
            default:
        }

        return attrs;
    }

    private List<ProductAttrVO> getLowerAttr(Product product) {
        List<ProductAttrVO> attrs = new ArrayList<>();
        switch (product.getType()) {
            case Product.TYPE_MEDICINE:
                Medicine medicine = this.medicineRepository.findByProductId(product.getId());
                if (medicine != null) {

                    attrs.add(new ProductAttrVO("【药品名称】", medicine.getName()));
                    attrs.add(new ProductAttrVO("【通用名】", medicine.getCommonName()));
                    attrs.add(new ProductAttrVO("【汉语拼音】", medicine.getPinyin()));
                    attrs.add(new ProductAttrVO("【成份】", medicine.getIngredients()));
                    attrs.add(new ProductAttrVO("【性状】", medicine.getPhenotypicTrait()));
                    attrs.add(new ProductAttrVO("【功能主治】", medicine.getIndications()));
                    attrs.add(new ProductAttrVO("【用法用量】", medicine.getUsageDosage()));
                    attrs.add(new ProductAttrVO("【不良反应】", medicine.getAdverseEffects()));
                    attrs.add(new ProductAttrVO("【禁忌】", medicine.getContraindications()));
                    attrs.add(new ProductAttrVO("【注意事项】", medicine.getMattersNeedingAttention()));
                    attrs.add(new ProductAttrVO("【贮藏】", medicine.getStorage()));
                    attrs.add(new ProductAttrVO("【规格】", medicine.getSpecification()));
                    attrs.add(new ProductAttrVO("【有效期】", medicine.getPeriodValidity()));
                    attrs.add(new ProductAttrVO("【执行标准】", medicine.getExecutionStandard()));
                    attrs.add(new ProductAttrVO("【批准文号】", medicine.getApprovalNumber()));
                    attrs.add(new ProductAttrVO("【生产企业】", medicine.getProductionEnterprise()));
                }
                break;
            default:
        }
        return attrs;
    }
}
